/**
 *  CloudEdit- Editor colaborativo peer-to-peer
 *  Author: Miguel Souto Bartolomé
 *  Web: http://code.google.com/p/cloudedit/
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.google.gwt.cloudedit.server;

import java.util.ArrayList;
import java.util.Iterator;

import javax.servlet.ServletContext;

import rice.p2p.commonapi.NodeHandle;
import easypastry.cast.CastContent;
import easypastry.cast.CastListener;

/**
 * Listener de una red Pastry de tabla Hash distribuida para recibir eventos
 * Cast en forma de mensajes XML. Implementa los métodos de la clase
 * CastListener, permitiendo que el nodo permanezca a la escucha de los mensajes
 * Cast que le lleguen. El último mensaje del grupo al que está suscrito se
 * almacenará en el contexto de la sesión del cliente.
 * 
 * @author Miguel Souto Bartolomé
 * @version 4.0
 */
public class MensajesListener implements CastListener {

	/** Contexto del Servlet. */
	private ServletContext contexto;

	/**
	 * Instancia un nuevo mensajes listener.
	 * 
	 * @param contexto contexto del Servlet
	 */
	public MensajesListener(ServletContext contexto) {
		this.contexto = contexto;
	}

	/**
	 * Método que escucha un mensaje Anycast y devuelve cierto. Stub para
	 * posibles implementaciones posteriores.
	 * 
	 * @param content mensaje XML entrante
	 * @return cierto
	 * @see easypastry.cast.CastListener#contentAnycasting(easypastry.cast.CastContent)
	 */
	@Override
	public boolean contentAnycasting(CastContent content) {
		System.out.println("Llamada Anycast: " + content);
		return true;
	}

	/**
	 * Método que escucha un mensaje Cast de actualización de archivo entrante.
	 * Guarda el mensaje en el contexto de la sesión de cada cliente que esté 
	 * editando el mismo archivo. En caso de que ya hubiera un mensaje guardado
	 * se sobreescribe.
	 * 
	 * @param content el mensaje XML entrante
	 * @see easypastry.cast.CastListener#contentDelivery(easypastry.cast.CastContent)
	 */
	@SuppressWarnings("unchecked")
	@Override
	public synchronized void contentDelivery(CastContent content) {
		DatosMensaje mensaje = (DatosMensaje) content;
		Iterator<DatosCliente> itr = ((ArrayList<DatosCliente>) contexto
				.getAttribute("listeners")).iterator();
		while (itr.hasNext()) {
			DatosCliente elemento = itr.next();

			// Si el archivo ya existía en el listado lo borra y vuelve a
			// escribir
			if (elemento.getArchivo().equals(mensaje.getArchivo())) {
				if (!mensaje.getSesion().equals(
						elemento.getSesion().getId())) {
					elemento.getSesion().setAttribute(
							"mensaje",
							new DatosMensaje(mensaje.getSubject(), mensaje
									.getArchivo(), mensaje.getXML(),
									mensaje.getSesion()));
					System.out.println(elemento.getSesion().getId()
							+ " ha recibido : "
							+ elemento.getSesion().getAttribute("mensaje"));
				}
			}
		}		
	}

	/**
	 * Registra si un nodo se conecta o desconecta al grupo al que el nodo a la
	 * escucha está suscrito.
	 * 
	 * @param nh nodo que se conecta o desconecta
	 * @param joined si (join == true) el nodo se conecta, sino se desconecta
	 * @see easypastry.cast.CastListener#hostUpdate(rice.p2p.commonapi.NodeHandle,
	 *      boolean)
	 */
	@Override
	public void hostUpdate(NodeHandle nh, boolean joined) {
		if (joined)
			System.out.println("Node join : " + nh);
		else
			System.out.println("Node leave : " + nh);
	}

}